use std::sync::{atomic::AtomicBool, Arc};

use dfs::{
    inode::{inode_root, link_path_walk, set_current_path, DirCreateOptions},
    params::ParamCreateOptions,
};

/// 创建如下文件树
/// /
/// +-- test3
/// +-- dir1/
/// +-- dir2/
///       |
///       +-- test4
///       +-- test5
///       +-- dir2/
///       |     +-- test6
///       +-- dir3/
///             +-- dir5/
fn create_dfs_tree() {
    ParamCreateOptions::new()
        .read_write(true)
        .name("test3")
        .param_bool(inode_root(), Arc::new(AtomicBool::new(false)))
        .unwrap();

    DirCreateOptions::new().read_write(true).name("dir1").create_dir(inode_root()).unwrap();

    let inode =
        DirCreateOptions::new().read_write(true).name("dir2").create_dir(inode_root()).unwrap();

    ParamCreateOptions::new()
        .read_write(true)
        .name("test4")
        .param_bool(inode.clone(), Arc::new(AtomicBool::new(false)))
        .unwrap();
    ParamCreateOptions::new()
        .read_write(true)
        .name("test5")
        .param_bool(inode.clone(), Arc::new(AtomicBool::new(false)))
        .unwrap();

    let inode1 =
        DirCreateOptions::new().read_write(true).name("dir2").create_dir(inode.clone()).unwrap();

    ParamCreateOptions::new()
        .read_write(true)
        .name("test6")
        .param_bool(inode1, Arc::new(AtomicBool::new(false)))
        .unwrap();

    let inode1 =
        DirCreateOptions::new().read_write(true).name("dir3").create_dir(inode.clone()).unwrap();

    DirCreateOptions::new().read_write(true).name("dir5").create_dir(inode1).unwrap();
}

#[test]
fn path_link_walk() {
    create_dfs_tree();

    let inode = link_path_walk("/").unwrap();
    assert_eq!(inode.name(), inode_root().name());

    let inode = link_path_walk("/test3").unwrap();
    assert_eq!(inode.name(), "test3");

    let inode = link_path_walk("/test3/").unwrap();
    assert_eq!(inode.name(), "test3");

    let inode = link_path_walk("/dir1/").unwrap();
    assert_eq!(inode.name(), "dir1");

    let inode = link_path_walk("/dir1").unwrap();
    assert_eq!(inode.name(), "dir1");

    let inode = link_path_walk("/dir2/test4").unwrap();
    assert_eq!(inode.name(), "test4");

    let inode = link_path_walk("/dir2/test4/").unwrap();
    assert_eq!(inode.name(), "test4");

    let inode = link_path_walk("/dir2/dir2/test6").unwrap();
    assert_eq!(inode.name(), "test6");

    let inode = link_path_walk("//").unwrap();
    assert_eq!(inode.name(), inode_root().name());

    let inode = link_path_walk("//test3").unwrap();
    assert_eq!(inode.name(), "test3");

    let inode = link_path_walk("/dir2//dir2/test6").unwrap();
    assert_eq!(inode.name(), "test6");

    let inode = link_path_walk("/dir2//dir2/test6//").unwrap();
    assert_eq!(inode.name(), "test6");

    let inode = link_path_walk("/dir2/..").unwrap();
    assert_eq!(inode.name(), "/");

    let inode = link_path_walk("/dir2/../dir2").unwrap();
    assert_eq!(inode.name(), "dir2");

    let inode = link_path_walk("/dir2/../dir2/.").unwrap();
    assert_eq!(inode.name(), "dir2");

    let inode = link_path_walk("./dir2/../dir2/.").unwrap();
    assert_eq!(inode.name(), "dir2");

    let inode = link_path_walk("../dir2/../dir2/.").unwrap();
    assert_eq!(inode.name(), "dir2");

    let inode = link_path_walk("../dir2/../dir2/./test4").unwrap();
    assert_eq!(inode.name(), "test4");

    let parent = inode.parent().unwrap();
    assert!(parent.is_dir());
    assert_eq!(parent.name(), "dir2");

    let inode = link_path_walk("dir2").unwrap();
    set_current_path(inode).unwrap();
    let inode = link_path_walk(".").unwrap();
    assert_eq!(inode.name(), "dir2");

    let inode = link_path_walk("../dir1").unwrap();
    assert_eq!(inode.name(), "dir1");
}
